SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)


SET(PROTO_BIN_PATH ${PROTO_BASE}/bin)

##protoc              protoc-gen-doc  protoc-gen-gogo          protoc-gen-swagger
##protoc-gen-cpptags  protoc-gen-go   protoc-gen-grpc-gateway  protoc-gen-MICRO  grpc_cpp_plugin 


FIND_FILE(PROTOC protoc ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_DOC  protoc-gen-doc ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_GOGO  protoc-gen-gogo ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
#FIND_FILE(PBPULGIN_SWAGGER  protoc-gen-swagger ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_SWAGGER  protoc-gen-openapiv2 ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_CPPTAGS  protoc-gen-cpptags ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_GO  protoc-gen-go ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_GRPC_GW  protoc-gen-grpc-gateway ${PROTO_BIN_PATH} NO_DEFAULT_PATH)
FIND_FILE(PBPULGIN_GRPC  grpc_cpp_plugin ${PROTO_BIN_PATH} NO_DEFAULT_PATH)


FIND_FILE(PBPULGIN_MICRO  protoc-gen-micro ${PROTO_BIN_PATH} NO_DEFAULT_PATH)

IF (GRPC_BASE)
    SET(GPRC_PLUGIN_PATH ${GRPC_BASE}/bin)
    FIND_FILE(PBPULGIN_GRPC  grpc_cpp_plugin ${GPRC_PLUGIN_PATH} NO_DEFAULT_PATH)
    MESSAGE(STATUS "\t PBPULGIN_GRPC [${PBPULGIN_GRPC}]" )
ENDIF()

MESSAGE(STATUS "Protoc [${PROTOC}]" )
MESSAGE(STATUS "\t PBPULGIN_DOC [${PBPULGIN_DOC}]" )
MESSAGE(STATUS "\t PBPULGIN_GOGO [${PBPULGIN_GOGO}]" )
MESSAGE(STATUS "\t PBPULGIN_SWAGGER [${PBPULGIN_SWAGGER}]" )
MESSAGE(STATUS "\t PBPULGIN_CPPTAGS [${PBPULGIN_CPPTAGS}]" )
MESSAGE(STATUS "\t PBPULGIN_GO [${PBPULGIN_GO}]" )
MESSAGE(STATUS "\t PBPULGIN_GRPC_GW [${PBPULGIN_GRPC_GW}]" )
MESSAGE(STATUS "\t PBPULGIN_MICRO [${PBPULGIN_MICRO}]" )

function(proto_gen)
    set(_options APPEND_PATH DESCRIPTORS SINGLE_COMMAND)
    set(_singleargs TARGET LANGUAGE OUT_OPTS PROTOC_OUT_DIR)
    set(_multiargs PLIST OPTS)
	cmake_parse_arguments(pgc "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	
	MESSAGE(STATUS "TARGET[${pgc_TARGET}] LANGUAGE[${pgc_LANGUAGE}] OPTS[${pgc_OPTS}]")

	if (pgc_PLIST)	
		if (pgc_OUT_OPTS)
			SET(pgc_PROTOC_OUT "${pgc_OUT_OPTS}:${pgc_PROTOC_OUT_DIR}")
		else ()
			SET(pgc_PROTOC_OUT ${pgc_PROTOC_OUT_DIR})
		endif()		
		
		if (pgc_SINGLE_COMMAND)
			MESSAGE(STATUS "protobuf_generate [${pgc_PLIST}]")
			add_custom_command(TARGET ${pgc_TARGET}
				PRE_BUILD
				COMMAND mkdir ARGS -p ${pgc_PROTOC_OUT_DIR}
				COMMAND ${PROTOC} 
				ARGS ${pgc_OPTS}  ${pgc_PLIST} --${pgc_LANGUAGE}_out=${pgc_PROTOC_OUT}
				COMMENT "[proto_gen_${pgc_LANGUAGE} ${pgc_PLIST}]"
			)		
		else ()
			foreach(_file ${pgc_PLIST})
				MESSAGE(STATUS "protobuf_generate [${_file}]")
				add_custom_command(TARGET ${pgc_TARGET}
					PRE_BUILD
					COMMAND mkdir ARGS -p ${pgc_PROTOC_OUT_DIR}
					COMMAND ${PROTOC} 
					ARGS ${pgc_OPTS}  ${_file} --${pgc_LANGUAGE}_out=${pgc_PROTOC_OUT}
					COMMENT "[proto_gen_${pgc_LANGUAGE} ${_file}]"
				)
			endforeach()
		endif ()
	else()
		MESSAGE(STATUS "protobuf_generate no pgc_PLIST ")
	endif()	
endfunction()

function(proto_gen_cpp)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR )
    set(_multiargs PLIST OPTS)
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})

		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE cpp
			OPTS ${OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_cpp no pgc_PLIST ")
	endif()
	#MESSAGE(STATUS "/////////////////////////////////////proto_gen_cpp ${pgc_lang_PLIST} ")
endfunction()

function(proto_gen_cpptags)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR)
    set(_multiargs PLIST OPTS OUT_OPTS)
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-cpptags=${PBPULGIN_CPPTAGS})
		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE cpptags
			OPTS ${OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()
	#MESSAGE(STATUS "/////////////////////////////////////proto_gen_gogo ${pgc_lang_PLIST} ")
endfunction()

function(proto_gen_gogo)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS  )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-gogo=${PBPULGIN_GOGO})
		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE gogo
			OPTS ${OPTS}
			OUT_OPTS ${pgc_lang_OUT_OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()

endfunction()

function(proto_gen_go)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS  )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-gogo=${PBPULGIN_GOGO})
		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE go
			OPTS ${OPTS}
			OUT_OPTS ${pgc_lang_OUT_OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_go no pgc_PLIST ")
	endif()

endfunction()

function(proto_gen_grpc)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-grpc=${PBPULGIN_GRPC})
		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE grpc
			OPTS ${OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()
	
endfunction()

##生成grpc-gateway
function(proto_gen_grpc_gw)
    set(_options YAML APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}] [${pgc_lang_PLIST}]")
	if (pgc_lang_PLIST)
		foreach(_file ${pgc_lang_PLIST})
			set(OPTS ${pgc_lang_OPTS})
			list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
			list(APPEND OPTS --plugin=protoc-gen-grpc-gateway=${PBPULGIN_GRPC_GW})
			
			#如果YAML，表示使用YAML 指定的文件 进行处理
            #否则, 表示本地存在同名的yaml文件，
            #      如果有同名文件，则处理
            #      否则没有同名文件，则不处理
			if (pgc_lang_YAML)
                SET(YAML_FILE ${pgc_lang_YAML})
            else ()
				STRING( REGEX REPLACE "proto$" "yaml" YAML_FILE ${_file} )
            endif ()
            
            if (EXISTS ${YAML_FILE})
                #SET(OUT_OPTS "${pgc_lang_OUT_OPTS},grpc_api_configuration=${YAML_FILE}")
                SET(OUT_OPTS "logtostderr=true,grpc_api_configuration=${YAML_FILE}")
                MESSAGE(STATUS "$pgc_lang_OUT_OPTS ${pgc_lang_OUT_OPTS}")
                proto_gen(TARGET ${pgc_lang_TARGET}
                    PLIST ${_file}
                    LANGUAGE grpc-gateway
                    OPTS ${OPTS}
                    OUT_OPTS ${OUT_OPTS}
                    PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
                )
            else ()
               MESSAGE(STATUS "YAML FILE [${pgc_lang_YAML}] not exist") 
            endif ()    
		endforeach()
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()
	#MESSAGE(STATUS "/////////////////////////////////////proto_gen_gogo ${pgc_lang_PLIST} ")
endfunction()

##生成grpc-swagger
function(proto_gen_swagger)
    set(_options YAML APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}] [${pgc_lang_PLIST}]")
	if (pgc_lang_PLIST)
		foreach(_file ${pgc_lang_PLIST})
			set(OPTS ${pgc_lang_OPTS})
			list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
			list(APPEND OPTS --plugin=protoc-gen-swagger=${PBPULGIN_SWAGGER})
			
			#如果YAML，表示使用YAML 指定的文件 进行处理
            #否则, 表示本地存在同名的yaml文件，
            #      如果有同名文件，则处理
            #      否则没有同名文件，则不处理
			if (pgc_lang_YAML)
                SET(YAML_FILE ${pgc_lang_YAML})
            else ()
				STRING( REGEX REPLACE "proto$" "yaml" YAML_FILE ${_file} )
            endif ()
            
            if (EXISTS ${YAML_FILE})
                #SET(OUT_OPTS "${pgc_lang_OUT_OPTS},grpc_api_configuration=${YAML_FILE}")
                SET(OUT_OPTS "logtostderr=true,grpc_api_configuration=${YAML_FILE}")
                MESSAGE(STATUS "$OUT_OPTS ${OUT_OPTS}")
                proto_gen(TARGET ${pgc_lang_TARGET}
                    PLIST ${_file}
                    LANGUAGE swagger
                    OPTS ${OPTS}
                    OUT_OPTS ${OUT_OPTS}
                    PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
                )                    
            else ()
               MESSAGE(STATUS "YAML FILE [${YAML_FILE}]  not exist") 
            endif ()

			
		endforeach()
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()
	#MESSAGE(STATUS "/////////////////////////////////////proto_gen_gogo ${pgc_lang_PLIST} ")
endfunction()

##生成doc
function(proto_gen_doc)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS PLIST_REGEX)
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../doc
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../doc)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}] [${pgc_lang_PLIST}]")
	if (pgc_lang_PLIST)
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-doc=${PBPULGIN_DOC})
		##PLIST_REGX 存在，表示需要对PLIST进行匹配操作，符合要求的才能作为PLIST
		if (pgc_lang_PLIST_REGEX)
			SET(DOC_PLIST)
			foreach(_regex ${pgc_lang_PLIST_REGEX})
			MESSAGE(STATUS "%%%%%%%%%%%%%%%%%%%%%%%%%pgc_lang_PLIST_REGEX [${_regex}]")
				foreach(_file ${pgc_lang_PLIST})
					STRING(REGEX MATCH ${_regex} _temp ${_file})	
					if (_temp)
						LIST(APPEND DOC_PLIST ${_file})
					endif()	
				endforeach()
			endforeach()	
		else ()
			SET(DOC_PLIST ${pgc_lang_PLIST})
		endif()
		MESSAGE(STATUS "%%%%%%%%%%%%%%%%%%%%%%%%%DOC_PLIST [${DOC_PLIST}]")
		MESSAGE(STATUS "$pgc_lang_OUT_OPTS ${pgc_lang_OUT_OPTS}")
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${DOC_PLIST}
			LANGUAGE doc
			OPTS ${OPTS}
			OUT_OPTS ${OUT_OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
			SINGLE_COMMAND true
		)
	else()
		MESSAGE(STATUS "proto_gen_gogo no pgc_PLIST ")
	endif()

endfunction()

##生成MICRO
function(proto_gen_micro)
    set(_options APPEND_PATH DESCRIPTORS)
    set(_singleargs TARGET PROTO_FILE_PATH PROTOC_OUT_DIR OUT_OPTS)
    set(_multiargs PLIST OPTS  )
		
	cmake_parse_arguments(pgc_lang "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
	#proto文件所在路径
	if (pgc_lang_PROTO_FILE_PATH)
	else()
		set(pgc_lang_PROTO_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
	endif()
	#输出路径,默认为PROTO_FILE_PATH/../common/proto
	if (pgc_lang_PROTOC_OUT_DIR)
	else()
		set(pgc_lang_PROTOC_OUT_DIR ${pgc_lang_PROTO_FILE_PATH}/../common/proto/)
	endif()
	
	#MESSAGE(STATUS "TARGET[${pgc_lang_TARGET}]]")
	if (pgc_lang_PLIST)
		
		set(OPTS ${pgc_lang_OPTS})
		list(APPEND OPTS -I${pgc_lang_PROTO_FILE_PATH})
		list(APPEND OPTS --plugin=protoc-gen-micro=${PBPULGIN_MICRO})
		
		proto_gen(TARGET ${pgc_lang_TARGET}
			PLIST ${pgc_lang_PLIST}
			LANGUAGE micro
			OPTS ${OPTS}
			OUT_OPTS ${pgc_lang_OUT_OPTS}
			PROTOC_OUT_DIR ${pgc_lang_PROTOC_OUT_DIR}
		)
	else()
		MESSAGE(STATUS "proto_gen_micro no pgc_PLIST ")
	endif()

endfunction()

